package com.miniapi.api.services;

import java.time.LocalDateTime;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.miniapi.api.entities.QrCodeForPromotion;
import com.miniapi.api.entities.User;
import com.miniapi.api.repositories.QrCodeRepository;
import com.miniapi.api.repositories.UserRepository;

/**
 * Service class for handling WeChat subscribe and unsubscribe events.
 */
@Component
public class WeChatSubscribeService {
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private QrCodeRepository qrCodeRepository;

    /**
     * Handles the event when a user subscribes by scanning a QR code.
     * If the user is new and the ticket from the QR code is valid, links the
     * introducer.
     * 
     * @param openId The WeChat open ID of the user.
     * @param ticket The ticket identifier from the QR code scanned by the user.
     */
    public void handleSubscribeByScan(String openId, String ticket) {
        User user = ensureUser(openId);
        if (user.getTicket() == null) { // Checks if the ticket has not been set for a new user
            QrCodeForPromotion qrCode = qrCodeRepository.findQrCodeForPromotionByTicket(ticket);
            user.setTicket(ticket);
            user.setIntroducer(qrCode != null ? qrCode.getOwnerOpenId() : null); // Sets introducer if QR code is valid
        }
        updateSubscription(user, true); // Updates user subscription status to following
    }

    /**
     * Handles the event when a user unsubscribes.
     * 
     * @param openId The WeChat open ID of the user.
     */
    public void handleCancelSubscribe(String openId) {
        User user = ensureUser(openId);
        updateSubscription(user, false); // Updates user subscription status to not following
    }

    /**
     * Handles a direct subscription event without a QR code.
     * 
     * @param openId The WeChat open ID of the user.
     */
    public void handleSubscribe(String openId) {
        User user = ensureUser(openId);
        updateSubscription(user, true); // Reaffirms user's following status
    }

    /**
     * Ensures a user object exists in the repository or creates a new one if it
     * does not exist.
     * 
     * @param openId The WeChat open ID of the user.
     * @return User The user object, either retrieved or newly created.
     */
    private User ensureUser(String openId) {
        User user = userRepository.findByOpenId(openId);
        if (user == null) {
            user = new User(openId, null, false, null, LocalDateTime.now(), LocalDateTime.now());
            userRepository.save(user); // Creates and saves a new user if not found
        }
        return user;
    }

    /**
     * Updates the subscription status and the last updated time for the user.
     * 
     * @param user        The user to update.
     * @param isFollowing The new subscription status.
     */
    private void updateSubscription(User user, boolean isFollowing) {
        user.setFollowing(isFollowing);
        user.setUpdateTime(LocalDateTime.now()); // Sets the current time as the last update time
        userRepository.save(user); // Saves the updated user information
    }
}
